package com.inspur.dgov.bsp.user.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.inspur.dgov.bsp.user.entity.PubUser;
import com.inspur.dgov.bsp.user.entity.PubUserAvatar;
import com.inspur.dgov.bsp.user.entity.PubUserRole;
import com.inspur.dgov.bsp.user.service.PubUserAvatarService;
import com.inspur.dgov.bsp.user.service.PubUserRoleService;
import com.inspur.dgov.bsp.user.service.PubUserService;
import com.inspur.dgov.bsp.user.service.TreeService;
import com.inspur.dgov.bsp.user.vo.UserVO;
import com.inspur.dgov.common.secure.dto.SecureUser;
import com.inspur.dgov.common.secure.utils.SecureUtil;
import com.inspur.dgov.common.tool.api.R;
import com.inspur.dgov.common.tool.constant.AppConstant;
import com.inspur.dgov.common.tool.node.TreeNode;
import com.inspur.dgov.common.tool.utils.SMUtil;
import com.inspur.dgov.common.tool.utils.UniqueIdGenerator;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.configuration.DatabaseConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息 前端控制器
 * </p>
 *
 * @author chiyupei
 * @since 2020-06-01
 */
@RestController
@RequestMapping("/user")
@Slf4j
@Api(value = "用户信息管理", tags = "用户信息息接口")
public class PubUserController {

    @Autowired
    private PubUserService pubUserService;

    @Autowired
    private TreeService treeService;

    @Autowired
    private PubUserRoleService pubUserRoleService;

    @Autowired
    private PubUserAvatarService pubUserAvatarService;

    @Value("${tenant.default.id}")
    private String defaultTenantId;

    /**
     * 注入数据库常量配置
     */
    @Resource(name="databaseConfiguration")
    public DatabaseConfiguration systemConstant;

    /**
     * 用户信息分页列表
     *
     * @param nodeId
     * @param nodeType
     * @param query
     * @param page
     * @return
     */
    @PostMapping("/page")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "nodeId", value = "组织机构树节点ID", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "nodeType", value = "组织机构树节点类型", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "query", value = "查询条件", paramType = "query", dataType = "String")
    })
    @ApiOperation(value = "用户信息分页列表", notes = "传入组织机构树节点ID、组织机构树节点类型或查询条件", position = 1)
    public R<IPage<UserVO>> page(@RequestParam(value="nodeId", required = false) String nodeId,
                                 @RequestParam(value="nodeType", required = false) String nodeType,
                                 @RequestParam(value="query", required = false) String query, Page page) {
        Map<String, Object> params = new HashMap<>();
        //组织数据根据当前用户所属租户获取
        SecureUser curUser = SecureUtil.getUser();
        String tenantId = curUser.getTenantId();

        if (!tenantId.equals(this.defaultTenantId)) {
            params.put("tenantId", tenantId);
        }
        params.put("query", query);

        if (StrUtil.isNotBlank(nodeId)) {
            //根据节点类型设置不同查询参数，0:所属区划 1:组织类别 2:所属单位 3:所属部门 9:临时组织
            if ("0".equals(nodeType)) {
                params.put("regionId", nodeId);
            } else {
                params.put("organId", nodeId);
            }
        }

        IPage<UserVO> pages = this.pubUserService.selectUserPage(page, params);
        return R.data(pages);
    }

    /**
     * 用户树
     *
     * @param json
     * @return
     */
    @PostMapping("/userTree")
    @ApiOperation(value = "用户树", notes = "传入用户ID、所属区划ID", position = 2)
    public R<List<TreeNode>> userTree(@RequestBody JSONObject json) {
        PubUser user = new PubUser();
        //数据根据当前用户所属租户获取
        SecureUser curUser = SecureUtil.getUser();
        String tenantId = curUser.getTenantId();
        if (!this.defaultTenantId.equals(tenantId)) {
            user.setTenantId(Long.valueOf(tenantId));
        }
        String userId = json.getString("userId");
        if (StrUtil.isNotBlank(userId)) {
            user.setId(Long.valueOf(userId));
        }
        String regionId = json.getString("regionId");
        if (StrUtil.isNotBlank(regionId)) {
            user.setRegionId(Long.valueOf(regionId));
        }
        List<TreeNode> tree = this.treeService.userTree(user);
        return R.data(tree);
    }

    /**
     * 唯一性校验
     *
     * @param value
     * @param id
     * @return
     */
    @PostMapping("/verifyUnique")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "value", value = "区划编码", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "id", value = "区划ID", paramType = "query", dataType = "String")
    })
    @ApiOperation(value = "用户唯一性校验", notes = "传入用户账号和用户ID", position = 3)
    public R verifyUnique(@RequestParam(value = "value", required = true) String value,
                          @RequestParam(value = "id", required = false) String id) {
        if (StrUtil.hasEmpty(value)) {
            return R.fail("接口调用不合法");
        }

        QueryWrapper<PubUser> queryWrapper = new QueryWrapper<>();
        SecureUser curUser = SecureUtil.getUser();
        String tenantId = curUser.getTenantId();
        queryWrapper.lambda().eq(PubUser::getTenantId, tenantId);
        queryWrapper.lambda().eq(PubUser::getAccount, value);
        if (StrUtil.isNotEmpty(id)) {
            queryWrapper.lambda().ne(PubUser::getId, id);
        }

        //查出满足条件的所有记录
        List<PubUser> list = this.pubUserService.list(queryWrapper);
        if (ObjectUtil.isEmpty(list)) {
            return R.success("");
        }
        return R.fail("该用户账号已被使用");
    }

    /**
     * 新增用户信息
     *
     * @param user
     * @return
     */
    @PostMapping("/add")
    @ApiOperation(value = "新增用户信息", notes = "传入用户信息", position = 4)
    public R add(@RequestBody PubUser user) {
        SecureUser curUser = SecureUtil.getUser();
        LocalDateTime now = LocalDateTime.now();
        Long id = UniqueIdGenerator.generateId();
        user.setId(id);
        user.setTenantId(Long.valueOf(curUser.getTenantId()));
        user.setCreator(Long.valueOf(curUser.getUserId()));
        user.setCreateTime(now);
        user.setStatus(AppConstant.DB_STATUS_NORMAL);
        //根据身份证号解析民族、出生日期、性别
        String cardNo = user.getCardNo();
        if (StrUtil.isNotBlank(cardNo)) {
            String deCardNo = SMUtil.sm4Decrypt(cardNo);
            user.setGender(String.valueOf(IdcardUtil.getGenderByIdCard(deCardNo)));
            user.setBirthday(IdcardUtil.getBirthByIdCard(deCardNo));
        }
        boolean ret = this.pubUserService.save(user);
        return R.status(ret);
    }

    /**
     * 用户信息详情
     */
    @PostMapping("/detail")
    @ApiOperation(value = "用户信息详情", notes = "用户信息详情数据", position = 5)
    public R<UserVO> detail(@RequestBody PubUser user) {
        UserVO userVO = this.pubUserService.getUserInfo(user);
        return R.data(userVO);
    }

    /**
     * 更新用户信息
     *
     * @param user
     * @return
     */
    @PostMapping("/update")
    @ApiOperation(value = "更新用户信息", notes = "传入用户信息", position = 6)
    public R update(@RequestBody PubUser user) {
        SecureUser curUser = SecureUtil.getUser();
        LocalDateTime now = LocalDateTime.now();
        user.setUpdator(Long.valueOf(curUser.getUserId()));
        user.setUpdateTime(now);
        boolean ret = this.pubUserService.updateById(user);
        return R.status(ret);
    }

    /**
     * 重置密码
     * @param user
     * @return
     */
    @PostMapping("/reset")
    @ApiOperation(value = "重置密码", notes = "传入用户信息", position = 7)
    public R reset(@RequestBody PubUser user) {
        String defaultPass = this.systemConstant.getString("tenant.default.password");
        SecureUser curUser = SecureUtil.getUser();
        LocalDateTime now = LocalDateTime.now();
        user.setUpdator(Long.valueOf(curUser.getUserId()));
        user.setUpdateTime(now);
        user.setPassword(SMUtil.sm3Encrypt(defaultPass));
        boolean ret = this.pubUserService.updateById(user);
        return R.status(ret);
    }

    /**
     * 获取用户角色配置
     *
     * @param userIds
     * @return
     */
    @GetMapping("/userRole")
    @ApiOperation(value = "用户所分配的角色", notes = "用户所分配的角色", position = 8)
    public R<List<String>> userRole(@RequestParam(value = "userIds", required = true) String userIds) {
        List<String> list = new ArrayList<>();
        List<String> userIdList = StrUtil.split(userIds, ',');
        if (userIdList.size() > 1) {
            return R.data(list);
        }
        String userId = userIdList.get(0);
        List<PubUserRole> userRoles = this.pubUserRoleService.list(Wrappers.<PubUserRole>query().lambda()
                .eq(PubUserRole::getUserId, userId));
        list = userRoles.stream().map(item -> StrUtil.toString(item.getRoleId())).collect(Collectors.toList());
        return R.data(list);
    }

    /**
     * 用户角色权限设置
     *
     * @param json
     * @return
     */
    @PostMapping("/grant")
    @ApiOperation(value = "用户角色权限设置", notes = "传入角色IDS、用户IDS", position = 9)
    public R grant(@RequestBody JSONObject json) {
        String userIds = json.getString("userIds");
        List<String> userIdList = StrUtil.split(userIds, ',');
        boolean ret = false;
        for (String userId : userIdList) {
            ret = this.pubUserService.grant(json.getString("roleIds"), userId);
        }
        return R.status(ret);
    }

    /**
     * 获取用户头像
     *
     * @param userId
     *
     * @return
     */
    @ApiOperation(value = "用户头像", notes = "传入用户ID", position = 10)
    @GetMapping("/avatar")
    public R<String> avatar(@RequestParam(value = "userId", required = true) String userId) {
        String avatarImg = "";
        QueryWrapper<PubUserAvatar> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PubUserAvatar::getKind, AppConstant.DB_STATUS_NORMAL);
        queryWrapper.lambda().eq(PubUserAvatar::getUserId, userId);
        long startTime=System.currentTimeMillis();
        PubUserAvatar avatar = this.pubUserAvatarService.getOne(queryWrapper);
        long endTime=System.currentTimeMillis();
        System.out.println("程序运行时间1： "+(endTime - startTime)+"ms");
        startTime=System.currentTimeMillis();
        if (null != avatar) {
            String base64Code = Base64.encode(avatar.getContent());
            avatarImg = "data:image/jpeg;base64," + base64Code.replace("\r\n", "");
        }
        endTime=System.currentTimeMillis();
        System.out.println("程序运行时间2： "+(endTime - startTime)+"ms");
        return R.data(avatarImg);
    }

    /**
     * 用户图片上传
     */
    @PostMapping("/upload")
    @ApiOperation(value = "用户图片上传", notes = "传入用户图片及业务类型", position = 11)
    public R upload(@ApiParam(value = "文件内容", required = true) @RequestParam MultipartFile file) {
        try {
            String userId = SecureUtil.getUserId();
            //删除后新增
            UpdateWrapper<PubUserAvatar> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().eq(PubUserAvatar::getKind, AppConstant.DB_STATUS_NORMAL);
            updateWrapper.lambda().eq(PubUserAvatar::getUserId, userId);
            this.pubUserAvatarService.remove(updateWrapper);

            Long id = UniqueIdGenerator.generateId();
            LocalDateTime now = LocalDateTime.now();

            PubUserAvatar tfile = new PubUserAvatar();
            byte[] content = file.getBytes();
            tfile.setId(id);
            tfile.setUserId(Long.valueOf(userId));
            tfile.setKind(AppConstant.DB_STATUS_NORMAL);
            tfile.setName(file.getOriginalFilename());
            tfile.setExtType(file.getContentType());
            tfile.setSize(file.getSize());
            tfile.setContent(content);
            tfile.setCreator(Long.valueOf(userId));
            tfile.setCreateTime(now);
            this.pubUserAvatarService.save(tfile);

            String base64Code = Base64.encode(content);
            String base64Img = "data:image/jpeg;base64," + base64Code.replace("\r\n", "");
            return R.data(base64Img);
        } catch (IOException e) {
            log.error("单位文件上传失败", e);
        }
        return R.fail("上传失败");
    }
}
